package com.basic.juc;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * locate com.basic.juc
 * Created by mastertj on 2018/4/7.
 * 
 * 本类用于演示ThreadPoolExecutor的使用和配置
 * 
 * ThreadPoolExecutor是Java线程池的核心实现类，它提供了强大的线程池功能：
 * 1. 线程池可以有效控制线程的数量，避免线程数量过多导致系统资源耗尽
 * 2. 线程池可以重用已创建的线程，减少线程创建和销毁的开销
 * 3. 线程池提供了任务队列，可以存储等待执行的任务
 * 4. 线程池提供了拒绝策略，当任务过多时可以按照特定策略处理新任务
 * 
 * ThreadPoolExecutor的主要参数：
 * - corePoolSize: 核心线程数，线程池中保持活跃的最小线程数
 * - maximumPoolSize: 最大线程数，线程池中允许的最大线程数
 * - keepAliveTime: 空闲线程存活时间，超过核心线程数的线程在空闲时的最大存活时间
 * - workQueue: 工作队列，用于存放等待执行的任务
 * - threadFactory: 线程工厂，用于创建新线程
 * - handler: 拒绝策略，当任务太多无法处理时的策略
 */
/**
 * 线程池使用示例类
 * 演示ThreadPoolExecutor的基本用法和工作原理
 */
public class UseThreadPoolExecutors {
    /**
     * 主方法，创建线程池并提交任务
     * 
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 创建一个容量为3的有界阻塞队列，用于存放等待执行的任务
        final ArrayBlockingQueue blockingDeque = new ArrayBlockingQueue<Task>(3);

        /**
         * 线程池执行任务的流程：
         * 1. 当有新任务提交时，如果线程池中的线程数小于corePoolSize，则创建新线程执行任务
         * 2. 如果线程池中的线程数已经达到corePoolSize，则将新任务放入工作队列中
         * 3. 如果工作队列已满，且线程数小于maximumPoolSize，则创建新线程执行任务
         * 4. 如果工作队列已满，且线程数已经达到maximumPoolSize，则执行拒绝策略
         * 
         * 本例中的参数配置：
         * - corePoolSize = 1：核心线程数为1，表示线程池中会保持1个活跃线程
         * - maximumPoolSize = 2：最大线程数为2，表示线程池最多可以有2个线程同时执行任务
         * - keepAliveTime = 120秒：非核心线程的空闲存活时间
         * - workQueue = 容量为3的ArrayBlockingQueue：可以存放3个等待执行的任务
         */
        final ExecutorService executorService = new ThreadPoolExecutor(
                1, // corePoolSize - 核心线程数
                2, // maximumPoolSize - 最大线程数
                120L, // keepAliveTime - 空闲线程存活时间
                TimeUnit.SECONDS, // 时间单位
                blockingDeque // 工作队列
        );

        // 提交5个任务到线程池
        // 根据线程池执行规则：第1个任务会创建一个核心线程执行，第2-4个任务会放入队列，第5个任务会创建一个非核心线程执行
        executorService.execute(new Task(1, "task1")); // 由核心线程执行
        executorService.execute(new Task(2, "task2")); // 放入队列
        executorService.execute(new Task(3, "task3")); // 放入队列
        executorService.execute(new Task(4, "task4")); // 放入队列
        executorService.execute(new Task(5, "task5")); // 由非核心线程执行

        // 创建一个监控线程，每500毫秒打印一次队列大小
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 循环检查线程池是否已终止
                    while (!executorService.isTerminated()) {
                        Thread.sleep(500);
                        // 打印当前队列中等待执行的任务数量
                        System.out.println("Queue Size: " + blockingDeque.size());
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        // 关闭线程池，不再接受新任务，但已提交的任务会继续执行
        executorService.shutdown();
    }
}
